-- Generated from template

if IceLegend == nil then
	IceLegend = class({})
end

require('libraries/timers')
require('libraries/physics')
require "utils"


function Precache( context )
	--[[
		Precache things we know we'll use.  Possible file types include (but not limited to):
			PrecacheResource( "model", "*.vmdl", context )
			PrecacheResource( "soundfile", "*.vsndevts", context )
			PrecacheResource( "particle", "*.vpcf", context )
			PrecacheResource( "particle_folder", "particles/folder", context )
	]]
	PrecacheEveryThingFromKV( context )
end

-- Create the game mode when we activate
function Activate()
	GameRules.AddonTemplate = IceLegend()
	GameRules.AddonTemplate:InitGameMode()
end

function IceLegend:InitGameMode()
	print( "Template addon is loaded." )
	local gameMode = GameRules:GetGameModeEntity()
	gameMode:SetThink( "OnThink", self, "GlobalThink", 2 )
	gameMode:SetCameraDistanceOverride(1600)
	gameMode:SetModifyExperienceFilter(Dynamic_Wrap( IceLegend, "RemoveExp" ), self)
	gameMode:SetModifyGoldFilter(Dynamic_Wrap( IceLegend, "RemoveGold" ), self)
	gameMode:SetFogOfWarDisabled(true)
	ListenToGameEvent('npc_spawned', Dynamic_Wrap(IceLegend, 'OnNPCSpawned'), self)
	ListenToGameEvent( "entity_killed", Dynamic_Wrap( IceLegend, 'OnEntityKilled' ), self )
	ListenToGameEvent('player_chat', Dynamic_Wrap(IceLegend, 'OnPlayerMessage'), self)

	GameRules.damage = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
	GameRules.damage_team = {-1,0,0,-1,-1,0,-1,-1,-1,-1,-1,-1}

	GameRules:SetSameHeroSelectionEnabled(true)
	GameRules:SetPreGameTime(10.0)
	GameRules:SetHeroSelectionTime(20)
	if GameRules.SetStrategyTime then
		GameRules:SetStrategyTime(10)
	end
	if GameRules.SetShowcaseTime then
		GameRules:SetShowcaseTime(10)
	end
	GameRules:SetCustomGameTeamMaxPlayers( DOTA_TEAM_GOODGUYS, 3 )
	GameRules:SetCustomGameTeamMaxPlayers( DOTA_TEAM_BADGUYS, 3 )
	GameRules:SetCustomGameTeamMaxPlayers( DOTA_TEAM_CUSTOM_1, 3 )
	
	self:linkModifier()
end

function IceLegend:linkModifier( ... )
	
end

function IceLegend:RemoveGold( keys )
	return false
end

function IceLegend:RemoveExp(keys)
	return false
end

function IceLegend:OnPlayerMessage( event )
	local playerId = event.playerid
	local steamId = PlayerResource:GetSteamAccountID(playerId)
	print("playerId = ",playerId)
	if steamId~="135093847" and steamId~=135093748 then
		return false
	end
	local text = event.text

	if string.find(text,"-createunit") then
		local unitName = string.sub(text,13,string.len(text))
		local hero = PlayerResource:GetSelectedHeroEntity(playerId)

		local unit = CreateUnitByName(unitName, hero:GetAbsOrigin(), true, nil, nil, DOTA_TEAM_BADGUYS)
		if not unit then
			print("No Such UnitName")
			return false
		end
		unit:AddNewModifier(nil, nil, "modifier_phased", {duration=0.1}) 
		unit:SetControllableByPlayer(playerId, true)
	end
end

GameRules.PHYSIC_UNIT = {}
local init = false
local ingameinit = false
local totalPlayer = 0
local bossWave = 1


-- Evaluate the state of the game
function IceLegend:OnThink()
	local nNewState = GameRules:State_Get()
	if nNewState == DOTA_GAMERULES_STATE_STRATEGY_TIME then
		if not init then
			self:ForceAssignHeroes()
			Physics:GenerateAngleGrid()

			for i=1,16 do
				local id = i-1
				if PlayerResource:IsValidPlayerID(id) then
					local steamid = PlayerResource:GetSteamID(id)
					CustomNetTables:SetTableValue( "steamId", string.format( "%d", id ), { steamid=steamid } )
					CustomNetTables:SetTableValue( "primInfo", string.format( "%d", id ), { damage = 0 } )
					
				end
				CustomNetTables:SetTableValue( "teamInfo", string.format( "%d", i ), { damage = 0 } )
			end

			init = true
		end
		
	elseif nNewState == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then
		if not ingameinit then

			local music_mgr = require "music"
			music_mgr.play()

			--创建两个泉水
			local point1 = Entities:FindByName(nil,"npc_fountain_goodguy"):GetAbsOrigin()
			local point2 = Entities:FindByName(nil,"npc_fountain_badguy"):GetAbsOrigin()
			local point3 = Entities:FindByName(nil,"npc_fountain_team3"):GetAbsOrigin()
			local f1 = CreateUnitByName("npc_fountain_goodguy",point1, true, nil, nil, DOTA_TEAM_GOODGUYS)
			local f2 = CreateUnitByName("npc_fountain_badguy",point2, true, nil, nil, DOTA_TEAM_BADGUYS)
			local f3 = CreateUnitByName("npc_fountain_team3",point3, true, nil, nil, DOTA_TEAM_CUSTOM_1)
			Timers:CreateTimer(60 * 3, function()
				if bossWave < 5 then
					createBossFromSky("boss"..bossWave)
					bossWave = bossWave + 1
					return 60 * 3
				else
					return 60 * 100
				end
			end)
			Timers:CreateTimer(30,function() 
				flyToAndDropItem()
				return 30
			end)
			Timers:CreateTimer({
			    endTime = 15 * 60,
			    callback = function()
			    	--游戏时间结束，开始结算
			    	local maxId = 1
			    	local maxScore = -1
			    	local teamData = {}
			    	for i,v in ipairs(GameRules.damage_team) do
			    		if v > maxScore then
			    			maxScore = v
			    			maxId = i
			    		end
			    		if v > -1 then
			    			teamData[i] = v
			    		end

			    	end
			    	
			    	CustomGameEventManager:Send_ServerToAllClients("S2C_GAME_OVER",{teamData = teamData,primData = GameRules.damage,winTeam = maxId})
			    	Timers:CreateTimer({
			    		endTime = 2,
			    		callback = function()
			    			GameRules:SetGameWinner(maxId)
			    		end
			    		})
			    	
			    end
			})
			for i=1,10 do
				local id = i - 1
				if PlayerResource:IsValidPlayerID(id) then
					totalPlayer = totalPlayer + 1
					local hero = PlayerResource:GetSelectedHeroEntity(id)
					if hero then

						Physics:Unit(hero)
						hero:SetMass(60)
				  		hero:SetPhysicsFriction(0.2)
						GameRules.PHYSIC_UNIT[hero:GetEntityIndex()] = hero
						hero:SetNavCollisionType(PHYSICS_NAV_BOUNCE)
						hero:SetGroundBehavior (PHYSICS_GROUND_LOCK)
						hero:AdaptiveNavGridLookahead(true)
					  	hero:SetNavCollisionType(PHYSICS_NAV_BOUNCE)
					  	hero:SetPhysicsVelocityMax(4500)
					    hero:FollowNavMesh(true)
				
					end
				end
			end
			ingameinit = true
		end
	elseif nNewState >= DOTA_GAMERULES_STATE_POST_GAME then
		return nil
	end
	return 1
end

function IceLegend:OnNPCSpawned(keys)
	local npc = EntIndexToHScript(keys.entindex)  

	-- hero reflects colliding balls
	local playerID = npc:GetPlayerOwnerID()
	if playerID and not npc.physics then
		-- Physics:Unit(npc)
		-- npc:SetMass(60)
  -- 		npc:SetPhysicsFriction(0.2)
		-- GameRules.PHYSIC_UNIT[keys.entindex] = npc
		npc.physics = true
		local ability_hideen = npc:FindAbilityByName("zidan5")
		if ability_hideen then
			ability_hideen:SetLevel(1)
		end
		-- if npc:IsRealHero() then
		-- 	npc:AdaptiveNavGridLookahead(true)
		--   	npc:SetNavCollisionType(PHYSICS_NAV_BOUNCE)
		--   	npc:SetPhysicsVelocityMax(4500)
		--     npc:FollowNavMesh(true)
		--   	npc:SetGroundBehavior(PHYSICS_GROUND_LOCK)
		-- 	npc:OnPhysicsFrame(function (unit)
		-- 		local ang = unit:GetForwardVector():Normalized()
		-- 		print(ang)
		-- 		unit:SetPhysicsAcceleration(ang * 100)
		-- 		end)
		-- end
	end

end

--todo 在单位销毁的时候需要移除
function IceLegend:ForceAssignHeroes()
	for nPlayerID = 0, ( DOTA_MAX_TEAM_PLAYERS - 1 ) do
		local hPlayer = PlayerResource:GetPlayer( nPlayerID )
		if hPlayer then
			if not PlayerResource:HasSelectedHero( nPlayerID ) then
				hPlayer:MakeRandomHeroSelection()
			end
		end
	end
end

function PrecacheEveryThingFromKV( context )
    local kv_files = 
    {
	    "scripts/npc/npc_units_custom.txt",
	    "scripts/npc/npc_abilities_custom.txt",
	    "scripts/npc/npc_heroes_custom.txt",
	    "scripts/npc/npc_items_custom.txt"
	}
    for _, kv in pairs(kv_files) do
        local kvs = LoadKeyValues(kv)
        if kvs then
            print("BEGIN TO PRECACHE RESOURCE FROM: ", kv)
            PrecacheEverythingFromTable( context, kvs)
        end
    end

end
 
function PrecacheEverythingFromTable( context, kvtable)
    for key, value in pairs(kvtable) do
        if type(value) == "table" then
            PrecacheEverythingFromTable( context, value )
        else
            if string.find(value, "vpcf") then
                PrecacheResource( "particle",  value, context)
                print("PRECACHE PARTICLE RESOURCE", value)
            end
            if string.find(value, "vmdl") then  
                PrecacheResource( "model",  value, context)
                print("PRECACHE vmdl RESOURCE", value)
            end
            if string.find(value, "vsndevts") then
                PrecacheResource( "soundfile",  value, context)
                print("PRECACHE SOUND RESOURCE", value)
            end
        end
    end    
end
local bird = nil
function flyToAndDropItem()
	if not bird then
		bird = CreateUnitByName("npc_courier",Vector(0,0,0), true, nil, nil, DOTA_TEAM_CUSTOM_2)
	end
	local minx = -3289.41
	local miny = -3249.25
	local maxx = 3205.88
	local maxy = 3283
	local randx = RandomFloat(minx, maxx)
	local randy = RandomFloat(miny, maxy)
	local vec = Vector(randx,randy,0)
	vec = GetGroundPosition(vec,bird)
	local item = CreateItem("item_ability_point_ltx",nil,nil)
	bird:AddItem(item)
	local orderDrop = {
		UnitIndex = bird:entindex(),
		OrderType = DOTA_UNIT_ORDER_DROP_ITEM,
		AbilityIndex = item:entindex(),
		Position = vec,
		queue = true
	}
	ExecuteOrderFromTable(orderDrop)
end
--[[
	击杀BOSS的获得1000积分
]]

function IceLegend:OnEntityKilled( event )
	local killedUnit = EntIndexToHScript( event.entindex_killed )
	if killedUnit ~= nil then
		if killedUnit:IsRealHero() then
			self:OnEntityKilled_PlayerHero( event )
			return
		else
			local unitName = killedUnit:GetUnitName()
			if unitName:find("boss") then
				local killerUnit = EntIndexToHScript( event.entindex_attacker )
				local len = #unitName
				local bosslv = unitName:sub(len,len)
				local score = 1000 * bosslv
				updateRank(score,killerUnit,killedUnit)
				GameRules.PHYSIC_UNIT[event.entindex_killed] = nil
			end
		end
	end
end
local boss_run_time = 30

function IceLegend:OnEntityKilled_PlayerHero( event )
	local killedUnit = EntIndexToHScript( event.entindex_killed )
	local killerUnit = EntIndexToHScript( event.entindex_attacker )
	if killedUnit and killedUnit:IsRealHero() then

		local newItem = CreateItem( "item_tombstone",killedUnit , killedUnit )
		newItem:SetPurchaseTime( 0 )
		newItem:SetPurchaser( killedUnit )
		local tombstone = SpawnEntityFromTableSynchronous( "dota_item_tombstone_drop", {} )
		tombstone:SetContainedItem( newItem )
		tombstone:SetAngles( 0, RandomFloat( 0, 360 ), 0 )
		FindClearSpaceForUnit( tombstone, killedUnit:GetAbsOrigin(), true )
		--[[
			英雄被击杀获得300积分
		]]
		updateRank(300,killerUnit,killedUnit)
		dropAllItems(killedUnit)
		--15秒后没人救就复活
		if not killedUnit:IsReincarnating() then
			killedUnit:SetTimeUntilRespawn(15)
			return

		end
		
	end
end



--随机选择一个玩家的位置降临BOSS
function createBossFromSky(unitName)
	GameRules.inBossWave = true
	local idx = RandomInt(0,totalPlayer-1)
	local hero = PlayerResource:GetSelectedHeroEntity(idx)
	local pos = hero:GetAbsOrigin()
	local partID = ParticleManager:CreateParticle("particles/spawn/fromsky_"..unitName.."fly.vpcf",PATTACH_WORLDORIGIN,nil)
	ParticleManager:SetParticleControl(partID,0,pos + Vector(250,250,2000))
	ParticleManager:SetParticleControl(partID,1,pos)
	ParticleManager:SetParticleControl(partID,2,Vector(2.2,0,0))
	Timers:CreateTimer({
		endTime = 2.2,
		callback = function()
			local boss = CreateUnitByName(unitName,pos, true, nil, nil, DOTA_TEAM_CUSTOM_2)
			local p2 = ParticleManager:CreateParticle("particles/units/heroes/hero_warlock/warlock_rain_of_chaos_start.vpcf",PATTACH_ABSORIGIN_FOLLOW,boss)
			ParticleManager:SetParticleControl(p2,0,pos)
			EmitSoundOn("Hero_Brewmaster.ThunderClap",boss)
			GameRules.PHYSIC_UNIT[boss:GetEntityIndex()] = boss
			Physics:Unit(boss)
			boss:SetMass(60)
			boss:SetPhysicsFriction(0.2)
			-- local entindex = boss:GetEntityIndex()
			-- Timers:CreateTimer({
			-- 	endTime = boss_run_time,
			-- 	callback = function()
			-- 		GameRules.inBossWave = false
			-- 		local entry = EntIndexToHScript(entindex)
			-- 		if IsValidEntity(entry) then
			-- 			entry:ForceKill(false)
			-- 		end
			-- 	end
			-- })
		end
	})
end